package com.hxzy.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.sql.Order;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxzy.common.aspect.satoken.StpMobileUtil;
import com.hxzy.common.constants.MarketConstants;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.ServiceException;
import com.hxzy.controller.mobile.cart.resp.MobileCartResp;
import com.hxzy.controller.mobile.order.req.SubmitOrderReq;
import com.hxzy.entity.AddressBook;
import com.hxzy.entity.OrderDetail;
import com.hxzy.entity.Orders;
import com.hxzy.entity.Product;
import com.hxzy.service.*;
import com.hxzy.mapper.OrdersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

/**
* @author admin
* @description 针对表【orders(订单表)】的数据库操作Service实现
* @createDate 2024-02-21 11:30:41
*/
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
    implements OrdersService{

    /**
     * 订单明细业务逻辑
     */
    @Autowired
    private OrderDetailService orderDetailService;

    /**
     * 购物车业务逻辑
     */
    @Autowired
    private ShoppingCartService shoppingCartService;

    /**
     * 产品信息
     */
    @Autowired
    private ProductService productService;

    /**
     * 收货人地址
     */
    @Autowired
    private AddressBookService addressBookService;

    /**
     * 提交订单
     * 1、查询当前用户购物车的信息
     * 2、查询收货地址是不是你的
     * 3、对数据库product进行锁定（悲观锁/乐观锁），判断库存够不够
     * 4、向orders表写入订单
     * 5、向order_detail订单明细表中写入数据
     * 6、删除购物车数据
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String submit(SubmitOrderReq req) {

        long userId= StpMobileUtil.getLoginIdAsLong();

        //查询收货地址是不是你的
        AddressBook addressBook =this.addressBookService.getOne(new LambdaQueryWrapper<AddressBook>()
                .eq(AddressBook::getId,req.getAddressBookId())
                .eq(AddressBook::getUserId,userId)
                .eq(AddressBook::getIsDeleted, MarketConstants.ACCOUT_ENABLE));
        if(Objects.isNull(addressBook)){
            throw new ServiceException(AckCode.ADDRESS_NOT_USE);
        }

        //定义订单明细
        List<OrderDetail>  orderDetailList=new ArrayList<>();


        //总金额
         AtomicReference<BigDecimal> amoutDecimal=new AtomicReference<>(new BigDecimal("0.0"));

        //循环遍历购物车的信息，对product商品表进行乐观锁操作
        List<MobileCartResp> mobileCartResps = this.shoppingCartService.cartList(req.getMerchantId());

        mobileCartResps.forEach(p->{
            //购买数量
            Integer buyNumber = p.getNumber();
            //乐观锁,查询商品ID
            Product productDb = this.productService.getById(p.getDishId());
            //有限量
            if(productDb.getNum()!=-1){
                //判断库存
                if(buyNumber> productDb.getNum()){
                    throw new ServiceException(AckCode.PRODUCT_STOCK_INSU);
                }

                //先扣库存，防止别人做操作
                long count=this.productService.deduceNum(buyNumber,productDb);
                //更新商品库存失败
                if(count==0){
                    throw new ServiceException(AckCode.PRODUCT_CHANGE_NUM_ERROR);
                }
            }

            //创建订单明细
            OrderDetail  orderDetail=new OrderDetail();
            orderDetail.setNumber(buyNumber);
            orderDetail.setAmount(p.getAmount());
            orderDetail.setDishId(p.getDishId());
            orderDetail.setImage(productDb.getPicture());
            orderDetail.setName(productDb.getName());
            orderDetail.setMerchantId(req.getMerchantId());
            orderDetail.setDishFlavor(p.getDishFlavor());
            orderDetailList.add(orderDetail);

            //应收金额
            amoutDecimal.set( amoutDecimal.get().add(p.getAmount().multiply(new BigDecimal(buyNumber))));
        });


        //向订单表写入的数据
        Orders orders=new Orders();
        orders.setUserId(userId);
        orders.setMerchantId(req.getMerchantId());
        orders.setAddressBookId(req.getAddressBookId());
        orders.setNumber(IdUtil.getSnowflakeNextIdStr());
        orders.setStatus("1");
        orders.setOrderTime(new Date());
        orders.setPayMethod(req.getPayMethod()+"");
        orders.setAmount(amoutDecimal.get());
        orders.setRemark(req.getRemark());
        orders.setPhone(addressBook.getPhone());
        orders.setAddress( addressBook.getProvinceName()+addressBook.getCityName()+addressBook.getDistrictName()+addressBook.getDetail()  );
        orders.setUserName(StpMobileUtil.getMobileLoginResp().getUserName());
        if("0".equals(addressBook.getSex())){
            orders.setConsignee(addressBook.getConsignee() +"(先生)" );
        }else  if("1".equals(addressBook.getSex())){
            orders.setConsignee(addressBook.getConsignee() +"(女士)" );
        }else{
            orders.setConsignee(addressBook.getConsignee() );
        }
        //保存订单
        this.save(orders);

        //循环给订单明细赋值
        orderDetailList.forEach(s->{
            s.setOrderId(orders.getId());
        });
        //定入订单明细操作
        this.orderDetailService.saveBatch(orderDetailList);

        //删除用户这个商家的购物车信息
        this.shoppingCartService.cleanCart(req.getMerchantId());

        //返回订单号
        return orders.getNumber();
    }

    @Override
    public Orders getByOrderNumber(String orderNumber) {
        LambdaQueryWrapper<Orders> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(Orders::getNumber,orderNumber);
        return this.getOne(queryWrapper);
    }

    /**
     * 支付成功，更新数据库订单状态和第三方的支付金额
     * @param orderNumber
     * @param payDate
     * @param bigDecimal
     * @param alipayTradeNo
     * @return
     */
    @Override
    public boolean updatePayStatusByOrderId(String orderNumber, Date payDate, BigDecimal bigDecimal, String alipayTradeNo) {
        LambdaQueryWrapper<Orders> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(Orders::getNumber, orderNumber);

        Orders db = this.getOne(queryWrapper);
        db.setStatus("2");
        db.setPayPrice(bigDecimal);
        db.setPayReceipt(alipayTradeNo);
        db.setCheckoutTime(payDate);

        //通知商家，通知骑手，更新用户积分.....
        return this.updateById(db);
    }

    /**
     * 取消订单
     * @param outTradeNo
     * @return
     */
    @Override
    public boolean cancelCheckOutTime(String outTradeNo) {
        LambdaQueryWrapper<Orders> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(Orders::getNumber, outTradeNo);
        Orders db = this.getOne(queryWrapper);

        db.setStatus("5");
        if(StrUtil.isBlank(db.getRemark())){
            db.setRemark("由于支付异常，系统自动取消订单");
        }else{
            db.setRemark(db.getRemark()+"\n由于支付异常，系统自动取消订单");
        }
        return this.updateById(db);
    }
}




